#include "EmitterManager.h"
#include "../../source/Tiny XML/tinyxml.h"
#include "IEmitter.h"
#include "RectEmitter.h"
#include "PointEmitter.h"
#include "LineEmitter.h"
#include "CircleEmitter.h"
#include "ParticleFlyweight.h"
#include "../../Source/SGD Wrappers/SGD_String.h"
#include "../../Source/SGD Wrappers/CSGD_TextureManager.h"
#include <sstream>
using namespace std;
CEmitterManager::CEmitterManager(void)
{
}


CEmitterManager::~CEmitterManager(void)
{
	for(decltype(Emitters().size()) i = 0; i < Emitters().size(); ++i )
	{
		delete Emitters()[i];
	}
	Emitters().clear();
}

bool CEmitterManager::Load()
{
	// Create a TinyXML Document
	TiXmlDocument doc;
	// Attempt to read from the file
	if( doc.LoadFile( "../ParticleEditor/EmitterList.xml" ) == false )
		return false;
	// Access the root element
	TiXmlElement* pRoot = doc.RootElement();
	if( pRoot == nullptr )
		return false;

	//clear list of emitters, prep for overwrite
	Emitters().clear();

	TiXmlElement* pEmitter = pRoot->FirstChildElement( "Emitter" );
	while( pEmitter != nullptr )
	{

		//temp to store new loaded values
		IEmitter* FilledEmitter;
		CParticleFlyweight* FilledFlyweight = new CParticleFlyweight();

		//type check
		int etype = -1;
		pEmitter->Attribute("Shape", &etype);
		if(etype == -1)
			return false;
		else if(etype == 0)
			FilledEmitter = new CRectEmitter();
		else if(etype == 1)
			FilledEmitter  = new CPointEmitter();
		else if(etype == 2)
			FilledEmitter  = new CCircleEmitter();
		else if(etype == 3)
			FilledEmitter = new CLineEmitter();
		else if(etype == 4)
			FilledEmitter = new IEmitter();

		//read in the name of emitter
		const char* pText = pEmitter->GetText();
		FilledEmitter->Name(pText);

		double height;
		pEmitter->Attribute("Height", &height);
		FilledEmitter->Height((float)height);

		double width = 40;
		pEmitter->Attribute("Width", &width);
		FilledEmitter->Width((float)width);

		//note: include gravity here
		double GravX = 40;
		pEmitter->Attribute("GravityX", &GravX);
		FilledFlyweight->GravityX((float)GravX);
		double GravY = 40;
		pEmitter->Attribute("GravityY", &GravY);
		FilledFlyweight->GravityY((float)GravY);

		//note: include spawn rate here
		double SpawnRate;
		pEmitter->Attribute("SpawnRate", &SpawnRate);
		FilledEmitter->SpawnRate((float)SpawnRate);


		double StartScaleX;
		pEmitter->Attribute("MinScaleX", &StartScaleX);
		FilledFlyweight->MinScaleX((float)StartScaleX);
		double EndScaleX;
		pEmitter->Attribute("MaxScaleX", &EndScaleX);
		FilledFlyweight->MaxScaleX((float)EndScaleX);

		double StartScaleY;
		pEmitter->Attribute("MinScaleY", &StartScaleY);
		FilledFlyweight->MinScaleY((float)StartScaleY);
		double EndScaleY;
		pEmitter->Attribute("MaxScaleY", &EndScaleY);
		FilledFlyweight->MaxScaleY((float)EndScaleY);

		double MinRotation;
		pEmitter->Attribute("MinRotation", &MinRotation);
		FilledFlyweight->MinRotation((float)MinRotation);

		double MaxRotation;
		pEmitter->Attribute("MaxRotation", &MaxRotation);
		FilledFlyweight->MaxRotation((float)MaxRotation);


		double SColA = 40;
		pEmitter->Attribute("StartColorA", &SColA);
		FilledFlyweight->MinColorA((float)SColA);
		double SColR = 40;
		pEmitter->Attribute("StartColorR", &SColR);
		FilledFlyweight->MinColorR((float)SColR);
		double SColG = 40;
		pEmitter->Attribute("StartColorG", &SColG);
		FilledFlyweight->MinColorG((float)SColG);
		double SColB = 40;
		pEmitter->Attribute("StartColorB", &SColB);
		FilledFlyweight->MinColorB((float)SColB);

		double EColA = 40;
		pEmitter->Attribute("EndColorA", &EColA);
		FilledFlyweight->MaxColorA((float)EColA);
		double EColR = 40;
		pEmitter->Attribute("EndColorR", &EColR);
		FilledFlyweight->MaxColorR((float)EColR);
		double EColG = 40;
		pEmitter->Attribute("EndColorG", &EColG);
		FilledFlyweight->MaxColorG((float)EColG);
		double EColB = 40;
		pEmitter->Attribute("EndColorB", &EColB);
		FilledFlyweight->MaxColorB((float)EColB);

		int maxP = -1;
		pEmitter->Attribute("MaxParticles", &maxP);
		FilledEmitter->MaxParticles(maxP);

		double minVelX = 40;
		pEmitter->Attribute("StartVelocityX", &minVelX);
		FilledFlyweight->MinVelX((float)minVelX);
		double maxVelX = 40;
		pEmitter->Attribute("EndVelocityX", &maxVelX);
		FilledFlyweight->MaxVelX((float)maxVelX );
		double minVelY= 40;
		pEmitter->Attribute("StartVelocityY", &minVelY);
		FilledFlyweight->MinVelY((float)minVelY);
		double maxVelY= 40;
		pEmitter->Attribute("EndVelocityY", &maxVelY);
		FilledFlyweight->MaxVelY((float)maxVelY);

		double minLife= 40;
		pEmitter->Attribute("MinLifetime", &minLife);
		FilledFlyweight->MinLife((float)minLife );
		double maxLife= 40;
		pEmitter->Attribute("MaxLifetime", &maxLife);
		FilledFlyweight->MaxLife((float)maxLife);

		int loop = -1;
		pEmitter->Attribute("Looping", &loop);
		if(loop == 0)
			FilledEmitter->IsLooping(false);
		else if(loop == 1)
			FilledEmitter->IsLooping(true);

		int forward = -1;
		pEmitter->Attribute("Forward", &forward);
		if(forward== 0)
			FilledEmitter->Forward(false);
		else if(forward== 1)
			FilledEmitter->Forward(true);

		wostringstream wos;

		const char * path = pEmitter->Attribute("ImagePath");
		wos << path;
		int imgID = CSGD_TextureManager::GetInstance()->LoadTexture((const TCHAR *)wos.str().c_str());
		FilledFlyweight->ParticleImageID(imgID);

		//Add new Emitter and Flyweight to Vector of managed emitters
		FilledEmitter->Flyweight(FilledFlyweight);
		m_vEmitters.push_back(FilledEmitter);

		//continue the loop for other emitters
		pEmitter = pEmitter->NextSiblingElement("Emitter");
	}

	if(m_vEmitters.size() >= 1)
		return true;
	else 
		return false;
}

IEmitter* CEmitterManager::GetEmitter(int index)
{
	return this->m_vEmitters[index];
}